package com.freemypay.test.并发.线程之间的协作.notify和notifyAll;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class NotifyVsNotifyAll {
	public static void main(String[] args) throws Exception {
		ExecutorService exec = Executors.newCachedThreadPool();
		for (int i = 0; i < 5; i++) {
			exec.execute(new Task());
		}
		exec.execute(new Task2());
		Timer timer = new Timer();
		timer.scheduleAtFixedRate(new TimerTask() {
			boolean prod = true;
			
			@Override
			public void run() {
				if(prod) {
					System.out.println("\nnotify()");
					Task.blocker.prod();
					prod = false;
				} else {
					System.out.println("\nnotifyAll() ");
					Task.blocker.prodAll();
					prod = true;
				}
			}
		}, 400, 400); // Run every 4 second
		TimeUnit.SECONDS.sleep(5); // Run for a while...
		timer.cancel();
		System.out.println("\nTimer canceled");
		TimeUnit.MILLISECONDS.sleep(500);
		System.out.println("Task2.blocker.proAll() ");
		Task2.blocker.prodAll();
		TimeUnit.MILLISECONDS.sleep(500);
		System.out.println("\nShutting down");
		exec.shutdownNow(); // Interrupt all tasks
	}
}

class Blocker {
	
	synchronized void waitingCall() {
		
		try {
			// 同Thread.interrupted()效果
			/*for(;;) {
				wait();
				System.out.println(Thread.currentThread() + " ");
			}*/
			while(!Thread.interrupted()) {
				wait();
				System.out.println(Thread.currentThread() + " ");
			}
		} catch (InterruptedException e) {
			System.out.println("InterruptedException waitingCall()");
		}
	}
	
	synchronized void prod() {
		notify();
	}
	
	synchronized void prodAll() {
		notifyAll();
	}
}

class Task implements Runnable {
	static Blocker blocker = new Blocker();
	
	@Override
	public void run() {
		blocker.waitingCall();
	}
	
}

class Task2 implements Runnable {
	// A separate Blocker object
	static Blocker blocker = new Blocker();
	
	@Override
	public void run() {
		blocker.waitingCall();
	}
}
